import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)
import {clearLoginInfo} from "@/utils";


//备份原push方法
let originPush = VueRouter.prototype.push;
VueRouter.prototype.push = function (location, resolve, reject) {
    //return routerPush.call(this.location).catch(err=>err)
    if (resolve && reject) {//如果传了回调函数，直接使用
        originPush.call(this, location, resolve, reject)
    } else {//如果没有传回调函数，手动添加
        originPush.call(this, location, () => {
        }, () => {
        })
    }
}

// let originPush = VueRouter.prototype.push;
// VueRouter.prototype.push = function pushToLocation(location) {
//     return new Promise((resolve, reject) => {
//         // 调用原始的 push 方法，但只传递 location 参数
//         originPush.call(this, location, () => {
//             // 导航成功完成
//             resolve();
//         }, err => {
//             // 导航失败
//             reject(err);
//         });
//     });
// };


//静态路由
// import Home from '@/views/Home.vue';
// import About from '@/views/About.vue';
//
// const routes = [
//     { path: '/home', component: Home },
//     { path: '/about', component: About }
// ];

//路由懒加载，import关键字写在component中
//component: () => import('@/components/Login.vue')

//开发环境不使用懒加载，因为懒加载页面太多的话会造成webpack热更新太慢，所以只有生成环境的使用懒加载
//const _import = file => require('@/views/' + file + '.vue').default
//生产环境的为const _import =file => import('@/views/' + file + '.vue').default
//动态路由
const _import = file => require('@/views/' + file + '.vue').default

/*
* require 函数：
在 Node.js 和许多基于 Node.js 的构建工具（如 Webpack）中，
* require 函数用于同步地引入模块。在前端项目中，
* 特别是使用 Webpack 的 Vue 项目中，
* require 被用来加载 JavaScript 文件、CSS 文件、图片资源以及 Vue 组件等。*/

/*
* .default：
在 Vue 单文件组件（.vue 文件）中，
* 当这个文件被 require 或 import 引入时，
* 它默认导出一个 Vue 组件对象。
* 这个对象包含了模板、脚本和样式等信息。
* 为了访问这个导出的 Vue 组件对象，我们需要使用 .default 属性。*/
//全局路由
const globalRoutes = [
    {
        path: '/404',
        component: _import('404'),
        name: '404',
        meta: {
            title: '页面未找到',
        },
    },
    {
        path: '/login',
        component: _import('LoginView'),
        name: 'login',
        meta: {
            title: '登录',
        },
    },
]

// 主入口路由(需嵌套上左右整体布局)
const mainRoutes = {
    path: '/',
    component: _import('main/index'),
    name: 'main',
    redirect: {name: 'home'},
    meta: {title: '主入口整体布局'},
    children: [
        // 通过meta对象设置路由展示方式
        // 1. isTab: 是否通过tab展示内容, true: 是, false: 否
        // 2. iframeUrl: 是否通过iframe嵌套展示内容, '以http[s]://开头': 是, '': 否
        // 提示: 如需要通过iframe嵌套展示内容, 但不通过tab打开, 请自行创建组件使用iframe处理!
        {
            path: '/home',
            component: _import('main/HomeView'),
            name: 'home',
            meta: {
                title: '主页'
            }
        },
    ],
    // 加载页面之前判断是否为登录状态，从本地cookie获取token值，token不存在或token为空则清空登录信息且跳转去登陆页面
    //判断有没有token
    beforeEnter(to, from, next) {
        let token = sessionStorage.getItem('token')
        //判断存不存在token并且测试token是否能通过正则测试
        if (!token) {
            //清空当前token
            clearLoginInfo()
            next({name: 'login'})
        } else {
            next()
        }
    }
}

const router = new VueRouter({
    mode: 'hash',
    scrollBehavior: () => ({y: 0}), // 当切换到新路由时，想要页面滚到顶部
    isAddDynamicMenuRoutes: false, // 是否已经添加动态(菜单)路由
    routes: globalRoutes.concat(mainRoutes)

})

//主要功能为，判断你是否为登录状态以便判断你是否有权访问除了登录页面的其他页面
router.beforeEach((to, from, next) => {
    // 添加动态(菜单)路由
    // 1. 已经添加 or 全局路由, 直接访问
    // 2. 获取菜单列表, 添加并保存本地存储
    // fnCurrentRouteType为判断当前路由类型的函数
    if (router.options.isAddDynamicMenuRoutes || fnCurrentRouteType(to, globalRoutes) === 'global') {
        next()
    } else {
        //配置动态路由
        let menuList = sessionStorage.getItem('menus')
        //如果缓存中存在就跳转指定页面，否则就跳转login
        if (menuList) {
            // 动态路由
            menuList = JSON.parse(menuList)
            fnAddDynamicMenuRoutes(menuList)//添加动态路由
            router.options.isAddDynamicMenuRoutes = true
            next({...to, replace: true})  // 跳转指定页面

        } else {
            router.push({name: 'login'})
        }
    }
})


/**
 * 判断当前路由类型, global: 全局路由, main: 主入口路由
 * @param {*} route 当前路由
 * @param globalRoutes
 */
function fnCurrentRouteType(route, globalRoutes = []) {
    let temp = []
    for (let i = 0; i < globalRoutes.length; i++) {
        if (route.path === globalRoutes[i].path) {
            return 'global'
        } else if (globalRoutes[i].children && globalRoutes[i].children.length >= 1) {
            temp = temp.concat(globalRoutes[i].children)
        }
    }
    return temp.length >= 1 ? fnCurrentRouteType(route, temp) : 'main'
}


/**
 * 添加动态(菜单)路由
 * @param {*} menuList 菜单列表
 * @param {*} routes 递归创建的动态(菜单)路由
 */
function fnAddDynamicMenuRoutes(menuList = [], routes = []) {
    //每次调用方法初始化temp用于后续判断子路由是否已经完全添加完毕
    let temp = []
    for (let i = 0; i < menuList.length; i++) {
        //判断menuList中的这个subMenus子路由是否存在并且是否具有内容也就是>=1,那么就放在temp中
        if (menuList[i].subMenus && menuList[i].subMenus.length >= 1) {
            temp = temp.concat(menuList[i].subMenus)
        } else if (menuList[i].url && /\S/.test(menuList[i].url)) {
            //在menuList[i].url中匹配'/'开头的，并且把'/'替换为'',返回这个替换之后的值
            menuList[i].url = menuList[i].url.replace(/^\//, '')
            console.log(menuList[i])
            let route = {
                //为了让浏览器不误判/是子路由，所以把/改成-
                path: menuList[i].url.replace('/', '-'),
                component: null,
                name: menuList[i].url.replace('/', '-'),
                meta: {
                    menuId: menuList[i].id,
                    title: menuList[i].name,
                    parentId: menuList[i].parentId,
                    parentName: menuList[i].parentName,

                }
            };
            try {
                route['component'] = _import(`modules/${menuList[i].url}`) || null
            } catch (e) {
                console.log(e)
            }
            routes.push(route)
        }
    }
    if (temp.length >= 1) {
        fnAddDynamicMenuRoutes(temp, routes)
    } else {
        mainRoutes.name = 'main-dynamic'
        mainRoutes.children = routes
        router.addRoute(mainRoutes)
        router.addRoute({
            path: '*',
            redirect: {
                name: '404'
            }
        })
    }
}


export default router